﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PingIntranet
{
    public partial class Main : Form
    {
        protected ConcurrentDictionary<string, string> AvaliableData = new ConcurrentDictionary<string, string>();
        protected ConcurrentQueue<string> UsedData = new ConcurrentQueue<string>();
        protected int ipLen = 0;
        protected delegate void Update();
        protected object lockObject = new object();
        public Main()
        {
            InitializeComponent();
            // lblTip.Visible = false;
            comboBoxMyIp.DataSource = GetAddressIP();
        }

        private void UpdateData()
        {
            var ipCompare = new IpCompare();
            var list = UsedData.ToList();
            list.Sort(ipCompare);
            listBoxUesd.DataSource = list;

            var sortList = new SortedDictionary<string, string>(AvaliableData, ipCompare);
            listBoxAvaliable.DataSource = sortList.Select(p => p.Key + " > " + p.Value).ToList();

            if (ipLen == list.Count + sortList.Count)
            {
                if (lblTip.InvokeRequired)
                {
                    var delege = new Update(() => { lblTip.Text = "执行完成！！！"; });
                    lblTip.Invoke(delege, null);
                }
                else
                {
                    lblTip.Text = "执行完成！";
                }
                if (btnStart.InvokeRequired)
                {
                    var delege = new Update(() => { btnStart.Enabled = true; });
                    btnStart.Invoke(delege, null);
                }
                else
                {
                    btnStart.Enabled = true;
                }
            }
        }

        protected class IpCompare : IComparer<string>
        {
            public int Compare(string x, string y)
            {
                var xIp = x.Split('.');
                var yIp = y.Split('.');
                for (int i = 0, len = xIp.Count(); i < len; i++)
                {
                    var ret = string.Compare(xIp[i].PadLeft(3, '0'), yIp[i].PadLeft(3, '0'), StringComparison.CurrentCultureIgnoreCase);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }
                return 0;
            }
        }

        private void PingCompleted(object obj, PingCompletedEventArgs e)
        {
            var ip = e.UserState.ToString();
            switch (e.Reply.Status)
            {
                case IPStatus.Success:
                    UsedData.Enqueue(ip);
                    break;
                default:
                    AvaliableData.TryAdd(ip, e.Reply.Status.ToString());
                    break;
            }
            try
            {
                UpdateData();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "程序执行异常");
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                var selIp = comboBoxMyIp.Text.Trim();
                if (string.IsNullOrEmpty(selIp))
                {
                    return;
                }
                if (!Regex.IsMatch(selIp, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$"))
                {
                    MessageBox.Show("IP地址格式错误！", "提示");
                    return;
                }
                lblTip.Text = "执行中...";
                btnStart.Enabled = false;
                AvaliableData.Clear();
                UsedData = new ConcurrentQueue<string>();
                var ips = GetIntranetIPs(selIp);
                ipLen = ips.Count;
                UpdateData();
                Parallel.ForEach(ips, (ip) =>
                {
                    Ping ping = new Ping();
                    ping.PingCompleted += PingCompleted;
                    ping.SendAsync(ip, 5000, ip);
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "程序执行异常");
                btnStart.Enabled = true;
            }
        }

        /// <summary>
        /// 获取本地IP地址信息
        /// </summary>
        List<string> GetAddressIP()
        {
            var list = new List<string>();
            foreach (IPAddress iPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (iPAddress.AddressFamily.ToString() == "InterNetwork")
                {
                    list.Add(iPAddress.ToString());
                }
            }
            return list;
        }

        List<string> GetIntranetIPs(string ip, string mask = null)
        {
            var prev = ip.Substring(0, ip.LastIndexOf(".") + 1);
            var list = new List<string>();
            for (int i = 1; i < 255; i++)
            {
                list.Add(prev + i.ToString());
            }
            return list;
        }
    }
}
